Skip to content

feat(zpl): maintenance batch (^MA / ^MI / ^MW / ^JH) - #129

Merged
u8array merged 3 commits into
mainfrom
feat/zpl-maintenance-batch
Jun 4, 2026
Merged

u8array merged 3 commits into
mainfrom
feat/zpl-maintenance-batch

Conversation

@u8array

@u8array u8array commented Jun 4, 2026

Copy link
Copy Markdown
Owner

No description provided.

Adds four Setup-Script-channel commands and a dedicated Maintenance
tab in the printer-settings modal.

- ^MA (Maintenance Alert): type (H/R), print (Y/N), threshold,
  frequency, units (M/I/C). Blank slot in `print`/`units` falls
  back to spec defaults (Y / M) so partial dumps round-trip.
  frequency min=1 by deliberate parser stance; out-of-range and
  invalid type discarded.
- ^MI (Maintenance Info Message): paired with ^MA via a shared
  type discriminator. Enforced cross-field at the schema layer
  (superRefine) so a mismatched import is rejected; the UI
  cascades alert-type changes into the existing message so the
  invariant never trips silently.
- ^MW (Head Cold Warning): single Y/N flag.
- ^JH (Early Warning Settings): only f-slot (early-warning gate)
  and g-slot (head-cleaning interval, `<n>M`) modelled; sibling
  slots emit empty. The registry places ^JH BEFORE ^MA so the
  gate is in effect when the alert lands. The g-slot wire format
  is marked TODO HW-verify (Zebra docs are ambiguous between
  raw `<n>M` and an indexed 0..16 table).

UI surface:
- New `maintenance` PrinterSettingsTab + MaintenanceTab component
- Alert is fully clearable via the type select's default option;
  message text empty clears the message
- Defaults sourced from MAINTENANCE_ALERT_DEFAULTS (single source
  of truth shared by UI placeholder + parser blank-slot fallback)
- Hint shows the 63-char cap via `({MAINTENANCE_MESSAGE_MAX_LEN})`
  template, not a hardcoded string

Locales seeded English across 32 files; translators can refine.
Roadmap 98→102 / 202; READMEs Media-&-feed 8/10 and Print-quality
5/14.

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request implements the printer maintenance settings tab, supporting ZPL commands for maintenance alerts (^MA), custom messages (^MI), head cold warnings (^MW), and early warning maintenance (^JH). It introduces the MaintenanceTab UI component, updates the ZPL parser and setup script generator, adds validation schemas, and includes comprehensive unit tests and localization keys. Feedback on these changes highlights usability issues in the BoundedIntCell component (where inputs can get stuck on empty or clamp too aggressively during typing) and recommends managing input state locally with validation on blur. Additionally, the custom message input should validate against unsafe characters to prevent silent store rollbacks, and the newly added localization keys in non-English locale files should be translated from English.

Important

The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.

Comment thread src/components/PrinterSettings/MaintenanceTab.tsx Outdated
Comment thread src/components/PrinterSettings/MaintenanceTab.tsx
Comment thread src/components/PrinterSettings/MaintenanceTab.tsx Outdated
Comment thread src/locales/ar.ts
Gemini PR review plus four review-iterations surfaced a class of bugs
in the printer-settings tabs: typing or pasting a char the schema
rejects (^/~/,/control) causes patchPrinterProfile to roll back, and
the controlled input visibly freezes. The fix-attempt in the original
feat commit only handled the maintenance message field and used a
regex without the global flag, so only the first unsafe char was
stripped. The same bug class already shipped in IdentityTab
(printerName, printerDescription) and EncodingAndLanguageTab
(encodingTable).

This refactor:

- Introduces `SafeStringInput` in `zplFieldPrimitives` that sanitises
  user input before patching. Default sanitiser is the new
  `stripUnsafeChars` helper, backed by a module-level g-flagged regex
  (`setupScriptUnsafeCharGlobalRegex`) so the regex isn't reallocated
  per keystroke. The primitive routes IME composition through real
  `compositionstart`/`compositionend` events instead of an
  `instanceof InputEvent` probe (cross-browser flake) and resets the
  composition flag on `blur` so a focus-loss mid-composition doesn't
  leave it stuck. Sanitises on `compositionend` as a safety net for
  browsers that skip the trailing `input` event (older Safari, some
  Android IMEs). Trade-off: the caret jumps to end after a mid-string
  strip (acceptable vs. the caret-math gymnastics the first cut
  invited).

- Hoists the cross-field cascade out of the slice into a pure
  `normalizeMaintenanceTypes(merged, patch)` helper in
  `types/PrinterProfile`. Direction follows which side the patch
  object touches, so a future `^MA`-only-via-import or a
  message-side edit each get their cascade for free.

- Migrates `printerName`, `printerDescription`, `encodingTable`, and
  the maintenance message field to `SafeStringInput`. Migrates the
  alert `print`/`units` selects and the message-text row to
  `ZplSubField` so the label-to-input `htmlFor` link is consistent
  with the rest of the modal.

- Drops the `?? 0` / `?? 1` collapse in the BoundedIntControl
  onChange handlers. `readBoundedInt` lets sub-min positives through
  for asymmetric typing; the schema requires `>= min`, so the
  frequency cell gates the commit. Threshold (`min=0`) needs no
  gate.

1528 tests green.
@u8array

u8array commented Jun 4, 2026

Copy link
Copy Markdown
Owner Author

/gemini review

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request introduces support for ZPL maintenance commands (^MA, ^MI, ^MW, ^JH), including parsing, setup script generation, and a new Maintenance tab in the printer settings UI. It also introduces a SafeStringInput component to sanitize inputs and prevent frozen-field UX. The review feedback highlights two issues: first, BoundedIntControl lacks local state buffering, which can cause a reverting/frozen input UX when typing temporarily invalid values; second, the parser rejects the ^MA command if the threshold or frequency parameters are omitted, rather than falling back to default values.

Important

The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.

Comment thread src/components/PrinterSettings/zplFieldPrimitives.tsx
Comment thread src/lib/zplParser/handlers/setupScript.ts Outdated
@u8array

u8array commented Jun 4, 2026

Copy link
Copy Markdown
Owner Author

/gemini review

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request adds a new Maintenance tab to the printer settings, implementing support for ZPL II maintenance commands (^MA, ^MI, ^MW, ^JH). It includes updates to the ZPL parser, setup script generator, store schema, state migration logic (bumping the store version to 7), and localizations. Additionally, a new SafeStringInput component is introduced to sanitize inputs, and BoundedIntControl is refactored to manage local draft states. Feedback on the changes highlights a critical issue in SafeStringInput where raw intermediate values during IME composition are propagated directly to the store. Because the store rejects invalid patches, this can clobber active IME compositions for non-English users; SafeStringInput should manage its own local draft state to prevent this.

Important

The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.

Comment thread src/components/PrinterSettings/zplFieldPrimitives.tsx
^MA type codes were H/R, spec is R (replacement) / C (cleaning).
^MA units default was M, spec default is I (inches).
^MA threshold/frequency caps are type-dependent per spec: R=150000m,
C=2000m, enforced via superRefine.
^JH g-slot wire format is an indexed table (0..16 → 100M..900M), not
raw <n>M with suffix as previously emitted. UI now exposes the
discrete set via a select; the persisted meters value is constrained
to the indexed set.

A v6→v7 migration remaps maintenanceAlert/Message type 'H' → 'C'
('R' was already correct). The rehydrate fixpoint loop drops any
residual schema violations top-key-by-top-key, bailing to {} if no
present key can resolve the issue.

The MaintenanceTab type-select clamps stale threshold/frequency to
the new type's cap before patching, so a switch R→C with an
out-of-spec value can't trip the schema and silently snap the
dropdown back to R.

JH_SLOT_F/G hoisted to PrinterProfile.ts so generator + parser share
one definition; JH_SLOT_COUNT replaces the hard-coded 10.
@u8array
u8array force-pushed the feat/zpl-maintenance-batch branch from f3de5f5 to 33af452 Compare June 4, 2026 16:52
@u8array
u8array merged commit 75c2115 into main Jun 4, 2026
2 checks passed
@u8array
u8array deleted the feat/zpl-maintenance-batch branch June 4, 2026 16:54
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant